import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:path/path.dart' as path_helper;
import 'database_service.dart';
import 'metadata_extractor.dart';

// 扫描进度回调
typedef ScanProgressCallback = void Function(int processed, int total, String currentFile);

class MediaScanService {
  static const List<String> _supportedImageExtensions = [
    '.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp', '.tiff', '.tif',
    '.heic', '.heif', '.raw', '.cr2', '.nef', '.arw', '.dng'
  ];
  
  static const List<String> _supportedVideoExtensions = [
    '.mp4', '.mov', '.avi', '.mkv', '.webm', '.flv', '.wmv', '.m4v',
    '.3gp', '.mts', '.m2ts', '.ts'
  ];
  
  // 扫描指定目录
  static Future<ScanResult> scanDirectory(
    String directoryPath, {
    ScanProgressCallback? onProgress,
    bool recursive = true,
    bool forceRescan = false,
    int batchSize = 50, // 批量处理大小
  }) async {
    final stopwatch = Stopwatch()..start();
    
    try {
      // 清理不存在的文件记录
      await DatabaseService.cleanupNonExistentFiles();
      
      // 如果强制重新扫描，清除该目录的所有记录
      if (forceRescan) {
        await DatabaseService.clearDirectoryRecords(directoryPath);
      }

      // 获取所有媒体文件
      final allFiles = await _getAllMediaFiles(directoryPath, recursive: recursive);
      
      int processed = 0;
      int newFiles = 0;
      int updatedFiles = 0;
      int errors = 0;
      
      // 分批处理文件
      for (int i = 0; i < allFiles.length; i += batchSize) {
        final batch = allFiles.skip(i).take(batchSize).toList();
        
        for (final file in batch) {
          try {
            onProgress?.call(processed, allFiles.length, file.path);
            
            final stat = await file.stat();
            final isUpToDate = await DatabaseService.isFileUpToDate(
              file.path, 
              stat.modified.millisecondsSinceEpoch,
            );

            // 如果文件已是最新，跳过
            if (!forceRescan && isUpToDate) {
              processed++;
              continue;
            }

            final mediaType = _getMediaType(file.path);
            
            // 插入或更新基本文件信息
            final fileData = {
              'file_path': file.path,
              'file_name': path_helper.basename(file.path),
              'file_size': stat.size,
              'file_extension': path_helper.extension(file.path).toLowerCase(),
              'media_type': mediaType,
              'created_at': stat.changed.millisecondsSinceEpoch,
              'modified_at': stat.modified.millisecondsSinceEpoch,
              'scanned_at': DateTime.now().millisecondsSinceEpoch,
            };

            final fileId = await DatabaseService.insertOrUpdateMediaFile(fileData);
            
            // 提取并保存元数据
            if (mediaType == 'image') {
              final metadata = await MetadataExtractor.extractPhotoMetadata(file.path);
              if (metadata != null) {
                metadata['file_id'] = fileId;
                await DatabaseService.insertOrUpdatePhotoMetadata(metadata);
              }
            } else if (mediaType == 'video') {
              final metadata = await MetadataExtractor.extractVideoMetadata(file.path);
              if (metadata != null) {
                metadata['file_id'] = fileId;
                await DatabaseService.insertOrUpdateVideoMetadata(metadata);
              }
            }

            if (isUpToDate) {
              updatedFiles++;
            } else {
              newFiles++;
            }

          } catch (e) {
            debugPrint('处理文件失败: ${file.path} - $e');
            errors++;
          }
          
          processed++;
        }
        
        // 批次间短暂暂停，避免阻塞UI
        if (i + batchSize < allFiles.length) {
          await Future.delayed(const Duration(milliseconds: 10));
        }
      }

      stopwatch.stop();
      
      return ScanResult(
        totalFiles: allFiles.length,
        newFiles: newFiles,
        updatedFiles: updatedFiles,
        errors: errors,
        duration: stopwatch.elapsed,
        success: true,
      );
      
    } catch (e) {
      debugPrint('扫描目录失败: $directoryPath - $e');
      return ScanResult(
        totalFiles: 0,
        newFiles: 0,
        updatedFiles: 0,
        errors: 0,
        duration: stopwatch.elapsed,
        success: false,
        error: e.toString(),
      );
    }
  }

  // 获取所有媒体文件
  static Future<List<File>> _getAllMediaFiles(String directoryPath, {bool recursive = true}) async {
    final List<File> mediaFiles = [];
    final directory = Directory(directoryPath);
    
    if (!await directory.exists()) return mediaFiles;

    await for (final entity in directory.list(recursive: recursive, followLinks: false)) {
      if (entity is File && _isMediaFile(entity.path)) {
        mediaFiles.add(entity);
      }
    }

    return mediaFiles;
  }

  // 检查是否为媒体文件
  static bool _isMediaFile(String filePath) {
    final extension = path_helper.extension(filePath).toLowerCase();
    return _supportedImageExtensions.contains(extension) || 
           _supportedVideoExtensions.contains(extension);
  }

  // 获取媒体类型
  static String _getMediaType(String filePath) {
    final extension = path_helper.extension(filePath).toLowerCase();
    if (_supportedImageExtensions.contains(extension)) {
      return 'image';
    } else if (_supportedVideoExtensions.contains(extension)) {
      return 'video';
    }
    return 'unknown';
  }

  // 获取支持的文件扩展名列表
  static List<String> getSupportedImageExtensions() => List.from(_supportedImageExtensions);
  static List<String> getSupportedVideoExtensions() => List.from(_supportedVideoExtensions);
  static List<String> getAllSupportedExtensions() => [
    ..._supportedImageExtensions, 
    ..._supportedVideoExtensions
  ];
}

// 扫描结果类
class ScanResult {
  final int totalFiles;
  final int newFiles;
  final int updatedFiles;
  final int errors;
  final Duration duration;
  final bool success;
  final String? error;

  ScanResult({
    required this.totalFiles,
    required this.newFiles,
    required this.updatedFiles,
    required this.errors,
    required this.duration,
    required this.success,
    this.error,
  });

  @override
  String toString() {
    if (!success) {
      return '扫描失败: $error';
    }
    
    final errorText = errors > 0 ? '，$errors个文件处理失败' : '';
    return '扫描完成: $totalFiles个文件，新增$newFiles个，更新$updatedFiles个$errorText，耗时${duration.inSeconds}秒';
  }
}